<?php

/**
 * Initializes pmvc for the given path.  If a path is
 * given it should be the path to lib folder containg
 * the pmvc files.
 * @param string[optional] $pmvcLibPath
 */
function pmvc_initialize($pmvcLibPath=NULL) {

	// bail if we've already initialized
	global $PMVC_INITIALIZED;
	if ($PMVC_INITIALIZED) { return; }

	// setup lib path
	if ($pmvcLibPath==NULL) {
		$pmvcLibPath = dirname(__FILE__);
	}
	require_once($pmvcLibPath."/pmvc/ClassLoader.class.php");
	require_once($pmvcLibPath."/pmvc/FileSystemClassLoader.class.php");

	// add a root classloader
	pmvc_addClassLoader(new pmvc\FileSystemClassLoader(Array($pmvcLibPath)));
	$PMVC_INITIALIZED = TRUE;

}
global $PMVC_INITIALIZED;
$PMVC_INITIALIZED = FALSE;

/**
 * Convienience function for creating an XmlApplicationContext
 * from the given $contextFile and using the given $classPath.
 * @param mixed $context the app context
 * @param array $classPath the classpath
 */
function pmvc_createApplicationContext(
	$context, $classPath=Array(), $pmvcLibPath=NULL) {

	// initialize
	pmvc_initialize($pmvcLibPath);

	// add to the classpath
	pmvc_addClassPath($classPath);
	return new pmvc\XmlApplicationContext($context);
}

/**
 * Convienience function for invoking the MVC dispatcher.
 * TODO: explain how it sets up the environment
 * @param array,string $configuration
 * @param array $classPath
 */
function pmvc_dispatchRequest(
	$configuration=NULL, 
	$classPath=NULL,
	$pmvcLibPath=NULL) {

	// set default paths
	if ($configuration==NULL) {
		$configuration = dirname($_SERVER["SCRIPT_FILENAME"])."/WEB-INF/applicationContext.xml";
	}
	if ($classPath==NULL) {
		$classPath = Array(
			dirname($_SERVER["SCRIPT_FILENAME"])."/WEB-INF/classes",
			dirname($_SERVER["SCRIPT_FILENAME"])."/WEB-INF/lib"
		);
	}
	
	// nothing
	$app = NULL;
	if (is_array($configuration) || is_string($configuration)) {
		$app = pmvc_createApplicationContext(
			$configuration, $classPath, $pmvcLibPath);
	} else {
		throw new Exception(
			"Unknow context type passed to pmvc_dispatchRequest");
	}

	// create the dispatcher and do it
	$app->initialize();
	$dispatcher = new \pmvc\mvc\Dispatcher($app, $_SERVER["REQUEST_URI"]);
	$dispatcher->dispatch();
}

/**
 * Adds a {@link ClassLoader} to the class loading
 * sub system.
 * @param pmvc\ClassLoader $classLoader
 */
function pmvc_addClassLoader($classLoader) {
	global $PMVC_CLASSLOADERS;
	$loader = Array(
		"classLoader" => $classLoader,
		"func" => function($className)use($classLoader) {
			return $classLoader->loadClass($className);
		}
	);
	array_push($PMVC_CLASSLOADERS, $loader);
	spl_autoload_register($loader["func"], FALSE);
}
global $PMVC_CLASSLOADERS;
$PMVC_CLASSLOADERS = Array();

/**
 * Removes a {@link ClassLoader} from the class loading
 * sub system.
 * @param pmvc\ClassLoader $classLoader
 */
function pmvc_removeClassLoader($classLoader) {
	global $PMVC_CLASSLOADERS;
	$newLoaders = Array();
	for ($i=0; $i<count($PMVC_CLASSLOADERS); $i++) {
		$loader = $PMVC_CLASSLOADERS[$i];
		if ($loader["classLoader"]==$classLoader) {
			spl_autoload_unregister($loader["func"]);
		} else {
			array_push($newLoaders, $loader);
		}
	}
	$PMVC_CLASSLOADERS = $newLoaders;
}

/**
 * Adds the given classpath to the root class loader.
 * @param string $classPath the classpath
 */
function pmvc_addClassPath($classPath) {
	pmvc_addClassLoader(new pmvc\FileSystemClassLoader($classPath));
}

/**
 * Uses all of the registered class loaders to require
 * the given file.
 * @param $fileName the file to load
 */
function pmvc_requireFile($fileName) {
	global $PMVC_CLASSLOADERS;
	for ($i=count($PMVC_CLASSLOADERS)-1; $i>=0; $i--) {
		if ($PMVC_CLASSLOADERS[$i]["classLoader"]->requireFile($fileName)) {
			return TRUE;
		}
	}
	return FALSE;
}

/**
 * Checks to see if a variable has a value.
 * @param mixed $val
 */
function pmvc_hasVal($val) {
	return isset($val) && !empty($val) && $val!=NULL;
}

/**
 * Returns the value of a request parameter, or the default
 * value provided.
 * @param string $name the name of the request param
 * @param mixed $default the default value
 */
function pmvc_getRequestParam($name, $default=NULL) {
	return (pmvc_hasVal($_REQUEST) 
		&& array_key_exists($name, $_REQUEST) 
		&& pmvc_hasVal($_REQUEST[$name])) ? $_REQUEST[$name] : $default;
}

/**
 * Returns the value of a request parameter, or the default
 * value provided.
 * @param string $name the name of the request param
 * @param mixed $default the default value
 */
function pmvc_getSessionVar($name, $default=NULL) {
	return (pmvc_hasVal($_SESSION) 
		&& array_key_exists($name, $_SESSION) 
		&& pmvc_hasVal($_SESSION[$name])) ? $_SESSION[$name] : $default;
}

/**
 * Sets the value of a session variable.
 * @param string $name the name of the request param
 * @param mixed $value the value
 */
function pmvc_setSessionVar($name, $value=NULL) {
	if (isset($_SESSION) && $value!=NULL) {
		$_SESSION[$name] = $value;
	} else if (isset($_SESSION)
		&& $value==NULL
		&& array_key_exists($name, $_SESSION)) {
		unset($_SESSION[$name]);
	}
}

/**
 * Array value getter.
 */
function pmvc_getArrayVal($array, $key, $default=NULL) {
    return array_key_exists($key, $array) ? $array[$key] : $default;
}

?>